// Copyright (C) 1953-2022 NUDT
// Verilog module name - link_delay_calculate 
// Version: V4.1.0.20221207
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         
///////////////////////////////////////////////////////////////////////////

`timescale 1ns / 1ps

module link_delay_calculate 
(
        i_clk                  ,
        i_rst_n                ,
		
        iv_t1                  ,
        i_t1_valid                ,		
        iv_t4                  ,
        i_t4_valid                ,		
        iv_t1t4_port_id        ,

        iv_t2                  ,
        i_t2_valid                ,		
        iv_t3                  ,
        i_t3_valid                ,		
        iv_t2t3_port_id        ,
		
		ov_t1                  ,
		ov_t2                  ,
		ov_t3                  ,
		ov_t4                  ,
		ov_timestamps_port_id  ,
		o_timestamps_valid     ,
		
		ov_link_delay          ,
		ov_link_delay_id       ,
        o_link_delay_valid     		
		
);
// clk & rst
input                  i_clk  ;
input                  i_rst_n;

input       [79:0]     iv_t1                   ;	
input       [79:0]     iv_t4                   ;
input       [4:0]      iv_t1t4_port_id              ;	
input                  i_t1_valid              ;
input                  i_t4_valid              ;

input       [79:0]     iv_t2                   ;	
input       [79:0]     iv_t3                   ;
input       [4:0]      iv_t2t3_port_id              ;	
input                  i_t2_valid              ;
input                  i_t3_valid              ;

output reg  [79:0]     ov_t1                   ;
output reg  [79:0]     ov_t2                   ;	
output reg  [79:0]     ov_t3                   ;		
output reg  [79:0]     ov_t4                   ;
output reg  [4:0]      ov_timestamps_port_id           ;	
output reg             o_timestamps_valid              ;

output reg  [11:0]     ov_link_delay                   ;
output reg  [4:0]      ov_link_delay_id                ;	
output reg             o_link_delay_valid              ;	  
/////////////////////////////////////
reg  [79:0]     rv_t1                   ;
reg  [4:0]      rv_t1_port_id           ;
reg             r_t1_valid              ;
reg  [79:0]     rv_t2                   ;
reg  [4:0]      rv_t2_port_id           ;
reg             r_t2_valid              ;
reg  [79:0]     rv_t3                   ;
reg  [4:0]      rv_t3_port_id           ;
reg             r_t3_valid              ;
reg  [79:0]     rv_t4                   ;
reg  [4:0]      rv_t4_port_id           ;
reg             r_t4_valid              ;
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
		rv_t1               <= 80'b0;
		rv_t1_port_id       <= 5'b0 ;
		r_t1_valid          <= 1'b0 ;
		rv_t2               <= 80'b0;
		rv_t2_port_id       <= 5'b0 ;
		r_t2_valid          <= 1'b0 ;
		rv_t3               <= 80'b0;
		rv_t3_port_id       <= 5'b0 ;
		r_t3_valid          <= 1'b0 ;
		rv_t4               <= 80'b0;
		rv_t4_port_id       <= 5'b0 ;
		r_t4_valid          <= 1'b0 ;
    end
    else begin
        if(i_t1_valid)begin
			rv_t1               <= iv_t1;
			rv_t1_port_id       <= iv_t1t4_port_id ;
			r_t1_valid          <= 1'b1;
	    end
		else begin
			rv_t1               <= rv_t1;
			rv_t1_port_id       <= rv_t1_port_id ;
			r_t1_valid          <= r_t1_valid;		
		end
		
        if(i_t2_valid)begin
			rv_t2               <= iv_t2;
			rv_t2_port_id       <= iv_t2t3_port_id ;
			r_t2_valid          <= 1'b1 ;
	    end	
        else begin
			rv_t2               <= rv_t2;
			rv_t2_port_id       <= rv_t2_port_id ;
			r_t2_valid          <= r_t2_valid ;
        end		
		
        if(i_t3_valid)begin
			rv_t3               <= iv_t3;
			rv_t3_port_id       <= iv_t2t3_port_id ;
			r_t3_valid          <= 1'b1 ;
	    end
        else begin
			rv_t3               <= rv_t3;
			rv_t3_port_id       <= rv_t3_port_id ;
			r_t3_valid          <= r_t3_valid ;
        end		

        if(i_t4_valid)begin
			rv_t4               <= iv_t4;
			rv_t4_port_id       <= iv_t1t4_port_id ;
			r_t4_valid          <= 1'b1 ;
	    end
        else begin
			rv_t4               <= rv_t4;
			rv_t4_port_id       <= rv_t4_port_id ;
			r_t4_valid          <= r_t4_valid ;
        end		
	end
end
/////////////////////////////////////////
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n)begin
	    ov_t1                <= 80'b0;
	    ov_t2                <= 80'b0;
	    ov_t3                <= 80'b0;
		ov_t4                <= 80'b0;
		ov_timestamps_port_id<= 5'b0;
		o_timestamps_valid   <= 1'b0 ;
		
		ov_link_delay       <= 12'b0 ;
		ov_link_delay_id    <= 5'b0 ;
		o_link_delay_valid  <= 1'b0 ;
    end
    else begin
        if(i_t3_valid && (rv_t1_port_id == rv_t2_port_id) && (rv_t2_port_id == iv_t2t3_port_id) && (rv_t2_port_id == rv_t4_port_id))begin
			ov_t1                <= rv_t1;
			ov_t2                <= rv_t2;
			ov_t3                <= iv_t3;
			ov_t4                <= rv_t4;
			ov_timestamps_port_id<= iv_t2t3_port_id;
			o_timestamps_valid   <= 1'b1 ;
			
			ov_link_delay_id    <= iv_t2t3_port_id ;
			o_link_delay_valid  <= 1'b1 ;
			if((rv_t2[31:0] + rv_t4[31:0]) >= (rv_t1[31:0] + iv_t3[31:0]))begin
			    if((((rv_t2[31:0] + rv_t4[31:0]) - (rv_t1[31:0] + iv_t3[31:0])) >> 1) >= 32'hFFF)begin    
					ov_link_delay       <= 12'hFFF ;
                end
                else begin
                    ov_link_delay       <= ((rv_t2[31:0] + rv_t4[31:0]) - (rv_t1[31:0] + iv_t3[31:0])) >> 1 ;
                end				
			end
			else if((rv_t2[31:0] + rv_t4[31:0]) < (rv_t1[31:0] + iv_t3[31:0]))begin
			    if((((rv_t2[31:0] + rv_t4[31:0] + 32'd1000000000) - (rv_t1[31:0] + iv_t3[31:0])) >> 1) >= 32'hFFF)begin    
					ov_link_delay       <= 12'hFFF ;
                end
                else begin
                    ov_link_delay       <= ((rv_t2[31:0] + rv_t4[31:0] + 32'd1000000000) - (rv_t1[31:0] + iv_t3[31:0])) >> 1 ;	
                end					
			end
	    end
		else begin
			ov_t1                <= 80'b0;
			ov_t2                <= 80'b0;
			ov_t3                <= 80'b0;
			ov_t4                <= 80'b0;
			ov_timestamps_port_id<= 5'b0;
			o_timestamps_valid   <= 1'b0 ;
			
			ov_link_delay       <= 12'b0 ;
			ov_link_delay_id    <= 5'b0 ;
			o_link_delay_valid  <= 1'b0 ;
	    end
    end
end

endmodule